"""
计算是否涨跌停；
必须使用不复权数据计算；
支持自己估算
也支持输入涨跌停价判断
"""
import datetime

from jili.core.convert import str2datetime
from research.calcor.dim1.updownlimit_price import calc_downlimite_price,calc_uplimite_price
def isuplimit_flag_4(b,r=0.09,preclose="preclose"):
    close = b["close"]
    up_price = b[preclose]*(1+r)
    if close>= up_price:
        r = 1
    else:
        r = 0
    return r
def isuplimit_flag_3(b,up_price=None,preclose="preclose"):
    timekey = b["timekey"]
    obj = b["obj"]
    close = b["close"]
    if up_price is None:
        up_price = calc_uplimite_price(obj, b[preclose], timekey)
    if close>= up_price:
        r = 1
    else:
        r = 0
    return r
def isuplimit_flag_2(b,up_price=None,preclose="preclose"):
    timekey = b["timekey"]
    obj = b["obj"]
    close = b["high"]
    if up_price   is None:
        up_price = calc_uplimite_price(obj, b[preclose], timekey)
    if close>= up_price and b["open"]<b["close"]:
        r = 1
    else:
        r = 0
    return r
def isuplimit_flag_1(b,up_price=None,preclose="preclose"):
    timekey = b["timekey"]
    obj = b["obj"]
    close = b["high"]
    if up_price   is None:
        up_price = calc_uplimite_price(obj, b[preclose], timekey)
    if close>= up_price:
        r = 1
    else:
        r = 0
    return r
def isdownlimit_flag_4(b,r=0.09,preclose="preclose"):
    close = b["close"]
    down_price = b[preclose]*(1-r)
    if close<= down_price:
        r = 1
    else:
        r = 0
    return r
def isdownlimit_flag_3(b,down_price=None,preclose="preclose"):
    timekey = b["timekey"]
    obj = b["obj"]
    close = b["close"]
    if down_price is None:
        down_price = calc_downlimite_price(obj, b[preclose], timekey)
    if close<= down_price:
        r = 1
    else:
        r = 0
    return r
def isdownlimit_flag_2(b,down_price=None,preclose="preclose"):
    timekey = b["timekey"]
    obj = b["obj"]
    close = b["high"]
    if down_price   is None:
        down_price = calc_downlimite_price(obj, b[preclose], timekey)
    if close<= down_price and b["open"]>b["close"]:
        r = 1
    else:
        r = 0
    return r
def isdownlimit_flag_1(b,down_price=None,preclose="preclose"):
    timekey = b["timekey"]
    obj = b["obj"]
    close = b["high"]
    if down_price   is None:
        down_price = calc_downlimite_price(obj, b[preclose], timekey)
    if close<= down_price:
        r = 1
    else:
        r = 0
    return r
#复权数据下的粗略估算
class isupdownlimit_indays_bar:
    def __init__(self,indays=5,limittype="1",updown="up",err_rate=0.0001):
        """

        Args:
            timeperiod: 在多长时间内出过涨停或是跌停
            limittype: 1.到达过涨停价，2.到达涨停，收盘价>开盘价,3：封板，
            updown:up:涨停，down:跌停
        """
        self.timeperiod=indays
        self.data=[]
        self.timekey = None
        self.err_rate_up=1+err_rate
        self.err_rate_down = 1-err_rate
        self.f={
            "oncalc_1_up":self.oncalc_1_up,
            "oncalc_2_up": self.oncalc_2_up,
            "oncalc_3_up": self.oncalc_3_up,
            "oncalc_1_down": self.oncalc_1_down,
            "oncalc_2_down": self.oncalc_2_down,
            "oncalc_3_down": self.oncalc_3_down,
        }
        name="oncalc_"+limittype+"_"+updown
        self.oncalc=self.f[name]
        self.preclose=None
    def oncalc_1_up(self,b,timekey=None):
        rst = None
        if b   is not None:
            if self.preclose:
                timekey = b["timekey"]
                obj = b["obj"]
                close = b["high"]
                up_price = calc_uplimite_price(obj, self.preclose, timekey)
                if close * self.err_rate_up >= up_price:
                    r = 1
                else:
                    r = 0
                if timekey   is not None:
                    if timekey == self.timekey:
                        self.data[-1] = r
                    else:
                        self.data.append(r)
                        self.timekey = timekey
                else:
                    self.data.append(r)
                if len(self.data) > self.timeperiod:
                    self.data.pop(0)
                if len(self.data) == self.timeperiod:
                    rst = sum(self.data)
            self.preclose = b["close"]
        return rst
    def oncalc_3_up(self,b,timekey=None):
        rst = None
        if b   is not None:
            if self.preclose:
                timekey = b["timekey"]
                obj = b["obj"]
                close = b["close"]
                up_price=calc_uplimite_price(obj,self.preclose,timekey)
                if close*self.err_rate_up>=up_price:
                    r=1
                else:
                    r=0
                if timekey   is not None:
                    if timekey == self.timekey:
                        self.data[-1] = r
                    else:
                        self.data.append(r)
                        self.timekey = timekey
                else:
                    self.data.append(r)
                if len(self.data) > self.timeperiod:
                    self.data.pop(0)
                if len(self.data) == self.timeperiod:
                    rst = sum(self.data)
            self.preclose=b["close"]
        return rst
    def oncalc_2_up(self,b,timekey=None):
        rst = None
        if b   is not None:
            if self.preclose:
                timekey = b["timekey"]
                obj = b["obj"]
                close = b["high"]
                up_price = calc_uplimite_price(obj, self.preclose, timekey)
                if close * self.err_rate_up >= up_price and b["open"]<b["close"]:
                    r = 1
                else:
                    r = 0
                if timekey   is not None:
                    if timekey == self.timekey:
                        self.data[-1] = r
                    else:
                        self.data.append(r)
                        self.timekey = timekey
                else:
                    self.data.append(r)
                if len(self.data) > self.timeperiod:
                    self.data.pop(0)
                if len(self.data) == self.timeperiod:
                    rst = sum(self.data)
            self.preclose = b["close"]
        return rst
    def oncalc_1_down(self,b,timekey=None):
        rst = None
        if b   is not None:
            if self.preclose:
                timekey = b["timekey"]
                obj = b["obj"]
                close = b["low"]
                down_price = calc_downlimite_price(obj, self.preclose, timekey)
                if close * self.err_rate_down <= down_price:
                    r = 1
                else:
                    r = 0
                if timekey   is not None:
                    if timekey == self.timekey:
                        self.data[-1] = r
                    else:
                        self.data.append(r)
                        self.timekey = timekey
                else:
                    self.data.append(r)
                if len(self.data) > self.timeperiod:
                    self.data.pop(0)
                if len(self.data) == self.timeperiod:
                    rst = sum(self.data)
            self.preclose = b["close"]
        return rst
    def oncalc_3_down(self,b,timekey=None):
        rst = None
        if b   is not None:
            if self.preclose:
                timekey = b["timekey"]
                obj = b["obj"]
                close = b["close"]
                down_price = calc_downlimite_price(obj, self.preclose, timekey)
                if close * self.err_rate_down <= down_price:
                    r = 1
                else:
                    r = 0
                if timekey   is not None:
                    if timekey == self.timekey:
                        self.data[-1] = r
                    else:
                        self.data.append(r)
                        self.timekey = timekey
                else:
                    self.data.append(r)
                if len(self.data) > self.timeperiod:
                    self.data.pop(0)
                if len(self.data) == self.timeperiod:
                    rst = sum(self.data)
            self.preclose = b["close"]
        return rst
    def oncalc_2_down(self,b,timekey=None):
        rst = None
        if b   is not None:
            if self.preclose:
                timekey = b["timekey"]
                obj = b["obj"]
                close = b["low"]
                down_price = calc_downlimite_price(obj, self.preclose, timekey)
                if close * self.err_rate_down <= down_price and b["open"] > b["close"]:
                    r = 1
                else:
                    r = 0
                if timekey   is not None:
                    if timekey == self.timekey:
                        self.data[-1] = r
                    else:
                        self.data.append(r)
                        self.timekey = timekey
                else:
                    self.data.append(r)
                if len(self.data) > self.timeperiod:
                    self.data.pop(0)
                if len(self.data) == self.timeperiod:
                    rst = sum(self.data)
            self.preclose = b["close"]
        return rst
if __name__=="__main__":
    from functools import partial
    r=isuplimit_flag_3({"obj":"002962","timekey":datetime.datetime(2023,11,28),"close":15.42,"preclose":14.02})
    f = partial(isuplimit_flag_4, r=0.12)
    b = {"close": 1.12, "PreClose": 1}
    r=f(b,preclose="PreClose")
    print(r)